package reference;

import junit.framework.TestCase;
import map.Student;

import java.io.IOException;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadLocalTest extends TestCase {

    private static ThreadLocal<Object> threadLocal = new ThreadLocal<>();
    private static ThreadLocal<String> threadLocal2 = new ThreadLocal<>();


    public static void set() {
        Student student1 = new Student("12", 12);
        threadLocal.set(student1);
    }


    public static void main(String[] args) throws InterruptedException, IOException {
        set();

        Student student = new Student("1", 1);
        List<Student> students = Arrays.asList(student);

        WeakReference weakReference = new WeakReference<Student>(student);


        Student student2 = new Student("1", 1);
        List<Student> students2 = Arrays.asList(student2);
        SoftReference softReference = new SoftReference<Student>(student2);
        /*
        System.out.println("before gc" + weakReference.get());

        System.gc();
        System.gc();
        System.gc();
        System.gc();

        System.out.println("after gc:" + weakReference.get());
        */
        System.gc();
        System.gc();
        System.gc();
        Thread.sleep(3000L);
        //
        System.out.println("after gc:" + weakReference.get());
        System.out.println("after gc  softReference:" + softReference.get());
        System.out.println("after gc threadLocal :" + threadLocal.get());


        System.gc();
        System.gc();
        System.gc();
        System.gc();

        //Thread.sleep(3000L);

        System.out.println("after gc:" + threadLocal.get());


        //TimeUnit.SECONDS.sleep(2);
        for (int i = 0; i < 1; i++) {
            threadLocal = new ThreadLocal<>();

            if (i == 10) {
                System.gc();
                Thread.sleep(3000L);
                System.out.println("after gc" + threadLocal.get());
            }

            threadLocal.set(new Object());


            //System.out.println(threadLocal.get());
        }

        MyEntry myEntry = new MyEntry(new ThreadLocalTest());

        System.out.println("before gc" + myEntry.get());
        System.gc();
        Thread.sleep(3000L);

        System.out.println("after gc" + myEntry.get());

    }


    ThreadLocal<Object> objectThreadLocal = new ThreadLocal<>();

    public void testOverFlow() throws InterruptedException {

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1));

        for (int i = 0; i < 1; i++) {
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    objectThreadLocal.set(new byte[1024 * 1024 * 50]);
                    objectThreadLocal = null;
                    while (true) {
                        try {
                            Thread.sleep(1000L);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }
                }
            });
        }

        Thread.sleep(100000L);

    }
}

class MyEntry extends WeakReference<ThreadLocalTest> {

    public MyEntry(ThreadLocalTest referent) {
        super(referent);
    }
}


